#-*- coding: utf-8 -*-

#_______________________ Simple As FucK Image Downloader _______________________
#
#                                by newfagpower

"""
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

    © 2011 newfagpower

"""

# FIXME: infinite loop + memory overload when an image page link is given
#        occures if the image belongs to a group or a gallery

import os
import re
import urllib
import urllib2
import HTMLParser
import logging
log = logging.getLogger(__name__)

import downloader


class UnhandledUrl(Exception): pass


class Motherless(downloader.Base):
    """ motherless downloader """

    DOMAIN_LIST = ['motherless.com']
    _DEFAULT_NAME = 'images'
    _PAGE_URL = '{0}?page={1}'
    _IMAGE_PAGE_URL = 'http://motherless.com/{0}/{1}'
    
    _END_GALLERY = '<p class="gold">There are no images in this gallery.</p>'
    _END_GROUP = '<p>This group has no images.</p>'
    
    _TITLE_GALLERY_RE = '<div class="member-bio-username">(.*)</div>'
    _TITLE_GROUP_RE = '<h1 class="group-bio-name">[^>]*>([^<]*)</a>[\s]*</h1>'
    _IMAGE_PAGE_RE = 'href="/{0}/(.*)"'
    _IMAGE_URL_RE = '"(http://s[0-9]\..*)"'
    
    _GROUP = {
        'home': '/g/',
        'image': '/gi/',
        'video': '/gv/'
        }
    _GALLERY_HOME = '/G'    
    _GALLERY = {
        'image': '/GI',
        'video': '/GV'
        }

    def _get_image_page_url(self):
        # raises UnhandledUrl
        
        # motherless group
        for url_type in Motherless._GROUP.values():
            if self._url.find(url_type) >= 0:
                home_link = self._url.replace(url_type,
                                    Motherless._GROUP['home'])
                home_sublink = home_link[1 + home_link.index(
                                    Motherless._GROUP['home']):]
                image_link = self._url.replace(url_type,
                                    Motherless._GROUP['image'])
                return (home_sublink, image_link)
        # motherless gallery
        for url_type in Motherless._GALLERY.values():
            if self._url.find(url_type) >= 0:
                home_sublink = os.path.basename(self._url.replace(url_type,
                                    Motherless._GALLERY_HOME))
                image_link = self._url.replace(url_type,
                                    Motherless._GALLERY['image'])
                return (home_sublink, image_link)
        if self._url.find(Motherless._GALLERY_HOME) >= 0:
            home_sublink = os.path.basename(self._url)
            image_link = self._url.replace(Motherless._GALLERY_HOME,
                                    Motherless._GALLERY['image'])
            return (home_sublink, image_link)
        raise UnhandledUrl()

    def _get_page(self, url):
        # raises urllib2-exception
        
        f = urllib2.urlopen(url)
        # remove windows endlines
        html = f.read().replace('\r', '')
        f.close()
        return html

    def _retrieve_data(self):
        """ gives informations about the download,
        returns the download «name» and the images to download urls. """
        # raises UnhandledUrl
        # raises urllib2-exception

        (home_page_suburl, image_page_url) = self._get_image_page_url()
        print (home_page_suburl, image_page_url)
        page_num = 1
        page_html = ''
        while True:
            page_url = Motherless._PAGE_URL.format(image_page_url,
                                                    str(page_num))
            log.debug('downloading: {0}'.format(page_url))
            html = self._get_page(page_url)
            if (html.find(Motherless._END_GALLERY) >= 0 or
                html.find(Motherless._END_GROUP) >= 0):
                break
            page_html += html
            page_num += 1
        name = ''
        title_list = (re.findall(Motherless._TITLE_GALLERY_RE, page_html) +
                        re.findall(Motherless._TITLE_GROUP_RE, page_html))
        if title_list:
            name = (HTMLParser.HTMLParser().unescape(title_list[0]).
                                strip().replace(os.sep, '|'))
        else:
            name = Motherless._DEFAULT_NAME
        log.debug('nb pages: {0}'.format(page_html.count('<title>')))
        # fetch url_list
        image_list = re.findall(Motherless._IMAGE_PAGE_RE.
                                format(home_page_suburl), page_html)
        log.debug('nb images found: {0}'.format(len(image_list)))
        image_page_list = [Motherless._IMAGE_PAGE_URL.
                            format(home_page_suburl, x) for x in image_list]
        return (name, image_page_list)
        
    def download_image(self):
        ok = True
        if self._waiting_list:
            url = self._waiting_list[0]
            try:
                html = self._get_page(url)
                full_url_list = re.findall(Motherless._IMAGE_URL_RE, html)
                if full_url_list:
                    image_url = full_url_list[0]
                    filename = os.path.basename(image_url)
                    dest_filename = os.path.join(self._tmp_dir, filename)
                    urllib.urlretrieve(image_url, dest_filename)
            except Exception as e:
                # ignore exceptions
                log.warning('«{0}» cannot download image «{1}»: {2}'.
                                format(self._name, url, e))
            # FIXME: when the current image download fails it is ignored
            self._waiting_list.remove(url)
            self._downloaded_list.append(url)
        else:
            ok = False
        return ok

